import { director, _decorator } from 'cc';
import { NATIVE } from 'cc/env';
import { tyqSDK } from '../Managers/TyqSDK';
import { GLoginState, GNetCmd } from '../Constans/Conf1';
import ServerCtr from '../Network/ServerCtr';
import * as cc from 'cc';
const { ccclass, property } = _decorator;

@ccclass('WmSocket')
export class WmSocket {
	eventHandlers: any = [];

	public lastHeartbeatTime: number = 0;
	public isWsConnect: boolean = false;
	ws: WebSocket = null!;
	wxws: any = null;

	msgBuff: any = {}; //key为stickId, val为stick数组
	// Stick_Id = "stick_id"
	// Stick_Len = "stick_len"
	// Stick_No = "stick_no" //服务端不处理，只判断字符总长度，前端自己用是否发送结束
	// Stick_Body = "stick_val"
	/**
	 * 单例
	 */
	private static _instance: WmSocket;
	public static getInstance(): WmSocket {
		if (!this._instance) {
			this._instance = new WmSocket();
		}
		return this._instance;
	}

	private isFirst = true;

	constructor() {
		this.addListener();
	}

	addListener() {
		director.on("ws_reconnect", this.onReconnect, this);
		director.on("ws_close", this.onClose, this);
		director.on(GNetCmd.StickPack, this.respStickPack, this)
	}

	respStickPack(data: any) {
		// cc.log("粘包接受情况--", data)
		if (data["isEnd"] == false) {
			this.sendStickPack(data["stick_id"], data["idx"] + 1)
		} else {
			delete this.msgBuff[data["stick_id"]] //清空本地缓存
		}
	}

	getGuid() {
		let d = new Date().getTime();
		return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
			let r = (d + Math.random() * 16) % 16 | 0;
			d = Math.floor(d / 16);
			return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16);
		});
	}

	getTotalLen(arr: any[]) {
		let len = 0;
		for (let i = 0; i < arr.length; i++) {
			len += arr[i].length;
		}
		return len;
	}

	sendStickPack(uuid: string, i: number) {
		let data = {
			"cmd": GNetCmd.StickPack,
			"stick_id": uuid,
			"stick_len": this.getTotalLen(this.msgBuff[uuid]),
			"stick_val": this.msgBuff[uuid][i],
			"isEnd": i == this.msgBuff[uuid].length - 1,
			"isStart": i == 0,
			"idx": i
		}
		// cc.log("分段存储", data)
		WmSocket.getInstance().sendSP(JSON.stringify(data));
	}

	onReconnect() {
		// 重连..
		if (this.isFirst) {
			this.isFirst = false;
			this.connect();
			console.log("发起第一次连-------")
		} else {
			if (!this.isConnected()) {
				this.connect();
				console.log("发起重连-------")
			}
		}
	}

	onClose() {
		// 断开连接..
		if (!this.isConnected()) {
			return;
		}
		if (!WmSocket.getInstance().isWsConnect) {
			this.ws.close();
		} else {
			this.wxws.close();
		}
	}

	connect() {
		this.ws_connect();
	}

	ws_connect() {
		console.log("ws_connect...........................")
		try {
			// let cerUrl = cc.url.raw('resources/ssl/fishing.cer');
			// if (cc.loader.md5Pipe) {
			// 	cerUrl = cc.loader.md5Pipe.transformURL(cerUrl);
			// }
			// this._socket = new WebSocket(this._url, [], cerUrl);

			// let pemUrl = cc.url.raw("resources/ssl/5556166_obeliskgames.cn.cer");
			// cc.log(pemUrl)
			// pemUrl = cc.loader.md5Pipe.transformURL(pemUrl)
			// cc.log(pemUrl)
			// this.ws = new WebSocket(gl.ws_url,  pemUrl);

			if (NATIVE) {
				// let pemUrl = ;
				// pemUrl = loader.md5Pipe.transformURL(pemUrl)

				// let cerUrl = url.raw("resources/ssl/Digicert-OV-DV-root.cer");
				// if (loader.md5Pipe) {
				// 	cerUrl = loader.md5Pipe.transformURL(cerUrl);
				// }
				// this.ws = new WebSocket(gl.ws_url, null, cerUrl);

				this.ws = new WebSocket(tyqSDK.getUrl().wsUrl); // GNetConf.mrtgd_WsUrl

				// assetManager.getBundle('resources').load("ssl/www.obeliskgames.cn.cer", Asset, (err,res)=>{
				// 	// let pemUrl = url.raw("resources/5556166_obeliskgames.cn.cer");
				// 	// pemUrl = loader.md5Pipe.transformURL(pemUrl)
				// 	this.ws = new WebSocket(gl.ws_url,  res.nativeUrl);
				// });
			} else {
				this.ws = new WebSocket(tyqSDK.getUrl().wsUrl);
			}


		} catch (e) {
			console.error("网络连接异常 --- exception---------------- ", e);
		}

		this.ws.onopen = (event) => {
			this.isWsConnect = true;
			console.log("Send Text WS was opened.");
			ServerCtr.GetInstance().wxLoginBegin();
			// console.log("onopen this.ws.readyState:",this.ws.readyState);
			// Notifications.emit("ws_connect",{type:'connect'});
		};
		this.ws.onmessage = (event) => {
			// console.log("response text msg: " + event.data, event.data.toString());
			// console.log("onmessage this.ws.readyState:",this.ws.readyState);
			this.onMessage(event.data);
		};
		this.ws.onerror = (event) => {
			console.error("Send Text fired an error", event);
			ServerCtr.GetInstance().loginState = GLoginState.loginWithoutAccount;
			// console.log("onerror this.ws.readyState:",this.ws.readyState);
			// Notifications.emit("ws_connect",{type:'disconnect'});
		};
		this.ws.onclose = (event) => {
			this.isWsConnect = false;
			console.log("WebSocket instance closed.");
			ServerCtr.GetInstance().loginState = GLoginState.loginWithoutAccount;
			// console.log("onclose this.ws.readyState:",this.ws.readyState);
			// Notifications.emit("ws_connect",{type:'disconnect'});
		};
	}


	onMessage(resp: string) {
		let respJson = JSON.parse(resp)
		// log("onMessage resp base64解开后JSON对象:", respJson)
		// console.log("onMessage resp:", respJson.cmd, respJson)
		director.emit(respJson.cmd + "", respJson)
	}

	isConnected() {
		return this.isWsConnect;
	}
	sendSP(jsonData: string) {
		if (!this.isConnected()) {
			return;
		}
		this.ws.send(jsonData)//NetMgr.getInstance ().jsencrypt()
	}

	send(netdata: any) {
		// log("###isConnected :",this.isConnected())
		if (!this.isConnected()) {
			return;
		}
		//以下是粘包处理
		let jsonData = JSON.stringify(netdata.data);
		let ontTimeLimit = 109586 / 5  //这里差不错20k 109586/5，必须小于80k
		// log("-------粘包-------", jsonData.length, ontTimeLimit, jsonData.length/ontTimeLimit+1)
		if (jsonData.length > ontTimeLimit) {
			let str = jsonData
			let strArr = [];
			let n = jsonData.length / ontTimeLimit + 1;
			for (let i = 0, l = str.length; i < n; i++) {
				let a = str.slice(ontTimeLimit * i, ontTimeLimit * (i + 1));
				// let a = str.substr(i*ontTimeLimit,ontTimeLimit)
				// log("分段存储1111", a)
				strArr.push(a);
			}
			let uuid = this.getGuid()
			this.msgBuff[uuid] = strArr
			this.sendStickPack(uuid, 0);
			return
		}
		// let data = JSON.stringify(netdata.data)
		// log("### client send data base64处理:", data)
		this.ws.send(jsonData) //NetMgr.getInstance ().jsencrypt()

	}

}

